<前端>性能优化
http优化
- 减少单次请求时间
- 减少请求次数
webpack优化
- 提高构建速度
- bable-loader中使用 include 或 exclude 来帮我们避免不必要的转译,比如排除node_modules文件夹
- 使用DLLPlugin打包第三方库
- Happypack将 loader 由单进程转为多进程
- 使用tree-shaking删除冗余代码,UglifyJsPlugin
- webpack按需加载
- 使用CommonsChunkPlugin拆分公共代码,webpack4使用optimization.splitChunks
- https://crazyaguai.github.io/2019/01/15/webpack-CommonsChunkPlugin%E4%B8%8Eoptimization-splitChunks/
- 生产环境关闭source-map
- 压缩混淆代码,UglifyJsPlugin
- 长缓存优化
- html-webpack-inline-chunk-plugin提前加载manifest.js
服务器开启gzip
图片优化
- 一个像素对应的二进制位数越多,它可以表示的颜色种类就越多,成像效果也就越细腻,文件体积相应也会越大。一个二进制位表示两种颜色(0|1 对应黑|白),如果一种图片格式对应的二进制位数有 n 个,那么它就可以呈现 2^n 种颜色。
- JPEG/JPG:有损压缩、体积小、加载快、不支持透明
- 优点:有损压缩,即使被称为“有损”压缩,JPG的压缩方式仍然是一种高质量的压缩方式:当我们把图片体积压缩至原有体积的 50% 以下时,JPG 仍然可以保持住 60% 的品质。
- 使用场景:JPG 适用于呈现色彩丰富的图片,在我们日常开发中,JPG图片经常作为大的背景图、轮播图或 Banner 图出现。
- 缺点:处理矢量图形和 Logo等线条感较强、颜色对比强烈的图像时,人为压缩导致的图片模糊会相当明显。JPEG 图像不支持透明度处理。
- PNG-8 与 PNG-24:无损压缩、质量高、体积大、支持透明
- 使用场景:呈现小的 Logo、颜色简单且对比强烈的图片或背景等。
- SVG:文本文件、体积小、不失真、兼容性好
- 特性:SVG 与 PNG 和 JPG 相比,文件体积更小,可压缩性更强。图片可无限放大而不失真。SVG 是文本文件,可以直接写在html dom中。
- 局限:渲染成本比较高,有学习成本(是可编程的)。
- 使用场景:
- base64:文本文件、依赖编码、小图标解决方案
- Base64 是一种用于传输 8Bit 字节码的编码方式,通过对图片进行 Base64 编码,我们可以直接将编码结果写入 HTML 或者写入 CSS,从而减少 HTTP 请求的次数。
- 应用场景:小图标,更新频率非常低
- url-loader可配置转换为base64图
- WebP
- Google 专为 Web 开发的一种旨在加快图片加载速度的图片格式,它支持有损压缩和无损压缩。
- WebP 像 JPEG 一样对细节丰富的图片信手拈来,像 PNG 一样支持透明,像 GIF 一样可以显示动态图片——它集多种图片文件格式的优点于一身。
- 局限性:浏览器支持情况不好,增加服务器的负担(编码同样质量的WebP文件会占用更多的计算资源。)
浏览器缓存
- Memory Cache
- 指内存中的缓存,从优先级上来说,它是浏览器最先尝试去命中的一种缓存。从效率上来说,它是响应速度最快的一种缓存。
- Base64 格式的图片,几乎永远可以被塞进 memory cache,体积不大的 JS、CSS文件,也有较大地被写入内存的几率。
- Service Worker Cache
- Service Worker 是一种独立于主线程之外的 Javascript 线程。
- https://www.jianshu.com/p/62338c038c42
- HTTP Cache
- Push Cache
- Push Cache 是指 HTTP2 在 server push 阶段存在的缓存。
本地存储
- cookie
- 劣势:有体积上限(4KB),紧跟域名,会带来资源浪费,同一个域名下的所有请求,都会携带 Cookie。
- web storage
- 特性:存储容量大,仅位于浏览器端,不与服务端发生通信。
- Local Storage 与 Session Storage 的区别:生命周期,Local Storage 是持久化的本地存储,Session Storage 是临时性的本地存储。作用域,Local Storage、Session Storage 和 Cookie 都遵循同源策略。但 Session Storage 特别的一点在于,即便是相同域名下的两个页面,只要它们不在同一个浏览器窗口中打开,那么它们的 Session Storage 内容便无法共享(不同tab页面不能共享)。
使用CDN缓存
- CDN 的核心点有两个,一个是缓存,一个是回源(缓存过期向上层服务器请求资源)。
- CDN 往往被用来存放静态资源。“静态资源”,就是像JS、CSS、图片等不需要业务服务器进行计算即得的资源。
服务端渲染
浏览器运行机制
- 渲染过程:首先基于 HTML 构建一个 DOM 树,这棵 DOM 树与 CSS 解释器解析出的 CSSOM 相结合,就有了布局渲染树。最后浏览器以布局渲染树为蓝本,去计算布局并绘制图像,我们页面的初次渲染就大功告成了。
- CSS 优化
- CSS 选择符是从右到左进行匹配的。
- 避免使用通配符,只对需要用到的元素进行选择。
- 关注可以通过继承实现的属性,避免重复匹配重复定义。
- 少用标签选择器。如果可以,用类选择器替代。
- 减少选择器嵌套。
- CSS与JS加载顺序优化
- CSS 是阻塞的资源。浏览器在构建 CSSOM 的过程中,不会渲染任何已处理的内容。需要将它尽早、尽快地下载到客户端,以便缩短首次渲染的时间。
- JS 引擎是独立于渲染引擎存在的。当 HTML 解析器遇到一个 script 标签时,它会暂停渲染过程,将控制权交给 JS 引擎。JS 引擎对内联的 JS 代码会直接执行,对外部 JS 文件还要先获取到脚本、再进行执行。等 JS 引擎运行完毕,浏览器又会把控制权还给渲染引擎,继续 CSSOM 和 DOM 的构建。
- 通过对JS使用 defer 和 async 来避免不必要的阻塞。
- async 模式下,JS 不会阻塞浏览器做任何其它的事情。它的加载是异步的,当它加载结束,JS 脚本会立即执行。
- defer 模式下,JS 的加载是异步的,执行是被推迟的。等整个文档解析完成、DOMContentLoaded 事件即将被触发时,被标记了 defer 的 JS 文件才会开始依次执行。
- 脚本与 DOM 元素和其它脚本之间的依赖关系不强时,我们会选用 async;当脚本依赖于 DOM 元素和其它脚本的执行结果时,我们会选用 defer。
DOM优化
- DOM操作为什么慢:(1)JS 引擎和渲染引擎(浏览器内核)是独立实现的。用 JS 去操作 DOM 时依赖了桥接接口作为“桥梁”。(2)DOM 的修改引发样式的更迭,会触发回流或重绘。
- 回流(重排):当我们对 DOM 的修改引发了DOM几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)。时
- 重绘:当我们对 DOM 的修改导致了样式的变化、却并未影响其几何属性(比如修改了颜色或背景色)时。
- 重绘不一定导致回流,回流一定会导致重绘。回流比重绘做的事情更多,带来的开销也更大。
- 减少DOM操作
(1)使用js变量 (2)使用DocumentFragment(表示一个没有父级文件的最小文档对象,不是真实 DOM 树的一部分,它的变化不会引起 DOM 树的重新渲染的操作(reflow),且不会导致性能等问题。)https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment
1 | let container = document.getElementById('container') |
Event Loop 与异步更新
回流与重绘
- 触发回流:(1)几何属性有 width、height、padding、margin、left、top、border (2)节点的增减、移动等操作。(3)获取一些也定属性的值(需要即时计算),offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight
- (1)避免回流与重绘(用js变量将缓存属性值)(2)避免逐条改变样式(通过修改class修改style)(3)将DOM离线,设置display: none,之后再操作
- Flush对列
- 浏览器会缓存flush对列,优化Layout和Paint。
Lazy-Load优化首屏体验
- 监听屏幕加载页面
节流(throttle)与防抖(debounce)
性能监控
- chrome Performance面板
- LightHouse